package see.battle.gui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.UUID;

import see.battle.ApplicationControler;
import see.battle.Const;
import see.battle.Utils;
import see.battle.server.DeviceList;
import see.battle.server.Server;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

public class ActionSelection extends Activity {
  private static final int REQUEST_ENABLE_BT = 3;		
  private ActionSelectionView _actionSelectionView;
  public ArrayList<String> _existingRoomList = null;
  private BluetoothAdapter _BluetoothAdapter = null;
  private static final UUID MY_UUID_SECURE = //UUID.randomUUID();
    UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
  private Server _server;
  private Thread _serverThread;
  private ProgressDialog pd = null;
  AlertDialog alert;
  AlertDialog.Builder builder;
 
  public boolean onTouchEvent(MotionEvent e) {
    if (e.getActionMasked() == MotionEvent.ACTION_DOWN) {
      int w = _actionSelectionView.get_widthInPx();
      int h = _actionSelectionView.get_heightInPx();
      float x = e.getX();
      float y = e.getY();
      if (Utils.isInsideRect(x, y, w, h, 1)) {
        ServerSideConnector connector = new ServerSideConnector(this);
        Thread connectorThread = new Thread(connector);
        System.err.println("server starts to wait for device");
        pd = ProgressDialog.show(this, "Waiting", 
            "Waiting for second player...", true, true);
        connectorThread.start();
      } else if (Utils.isInsideRect(x, y, w, h, 2)) {
        Intent serverIntent = new Intent(this, DeviceList.class);
        startActivityForResult(serverIntent, 0);
      }
    }
    return true;
  }

  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
      connectDevice(data, true);
    }
  }

  private void connectDevice(Intent data, boolean secure) {
    String address = data.getExtras().getString(
        DeviceList.EXTRA_DEVICE_ADDRESS);
    BluetoothDevice device = _BluetoothAdapter.getRemoteDevice(address);
    ClientSideConnector connector = new ClientSideConnector(device, this);
    Thread connectorThread = new Thread(connector);
    System.err.println("client starts connecting to device");
    System.err.println(address);
    pd = ProgressDialog.show(this, "Connecting", 
        "Connecting to server...", true, true);
    connectorThread.start();
  }

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
        WindowManager.LayoutParams.FLAG_FULLSCREEN);
    _BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (_BluetoothAdapter == null) {
      System.out.print("Bluetooth is not available");
      finish();
      return;
    }
    showErrorMessage();
  }
  @Override
  public void onStart() {
    super.onStart();
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    _actionSelectionView = new ActionSelectionView(this, metrics);
    setContentView(_actionSelectionView);
    if (!_BluetoothAdapter.isEnabled()) {
      Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
      startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
    }
  }
  
  public void showErrorMessage() {
  	builder = new AlertDialog.Builder(this);
  	builder.setMessage("Can't connect to this server. Please try again.")
  	       .setCancelable(false)
  	       .setPositiveButton("OK", new DialogInterface.OnClickListener() {
  	           public void onClick(DialogInterface dialog, int id) {
  	                dialog.dismiss();
  	           }
  	       });
  	alert = builder.create();
  }

  private class ServerSideConnector implements Runnable {
    
    Activity _parent;
    
    public ServerSideConnector(Activity parent) {
      _parent = parent;
    }

    //@Override
    public void run() {
      BluetoothServerSocket bss = null;
      BluetoothSocket bs = null;
      System.err.println("server side is started");
      try {
        bss = _BluetoothAdapter.listenUsingRfcommWithServiceRecord("secure", 
            MY_UUID_SECURE);
      } catch (IOException e) {
        e.printStackTrace();
      } finally {}
      try {
        bs = bss.accept();
      } catch (IOException e) {
        e.printStackTrace();
      }
      try {
        synchronized (bss) {
          bss.close();
        }
      } catch (IOException e1) {
        e1.printStackTrace();
      }
      System.err.println("bss is received");
      System.err.println("server side connection is established!");
      Message msg = new Message();
      Bundle bundle = new Bundle();
      bundle.putString("", "Device connection was not lost");
      msg.setData(bundle);
      System.err.println("send first message");
      handler.sendMessage(msg);
      _server = new Server(bs);
      ApplicationControler ac = (ApplicationControler)getApplicationContext();
      ac.set_server(_server);
      ac.set_serverSocket(bs);
      System.err.println("streams are received");
      _serverThread = new Thread(_server);
      _serverThread.start();
      Intent intent = new Intent(_parent, Game.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
      intent.putExtra("GAME_MODE", Const.localServer);
      startActivity(intent);
    }
    
    private Handler handler = new Handler() {
      //@Override
      public void handleMessage(Message msg) {
        pd.dismiss();
      }
    };
  }

  private class ClientSideConnector implements Runnable {
    
    private BluetoothDevice _device = null;
    Activity _parent;

    public ClientSideConnector(BluetoothDevice device, Activity parent) {
      _parent = parent;
      _device = device;
    }
    
    //@Override
    public void run() {
    	boolean error = false;
      BluetoothSocket bs = null;
      // Don't ask me why, but the following code helps to connect...
//      Process process = null;
//      try {
//        process = Runtime.getRuntime().exec("sdptool records " +
//            _device.getAddress());
//      } catch (IOException e2) {
//        e2.printStackTrace();
//      } try {
//        process.waitFor();
//      } catch (InterruptedException e2) {
//        e2.printStackTrace();
//      }
      // The end of strange code.
      try {
        bs = _device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
      } catch (IOException e) {
    	System.err.println("fail");
    	error = true;
    	handlerError.sendEmptyMessage(0);
      }
      System.err.println("before cancelling didcovery");
      _BluetoothAdapter.cancelDiscovery();
      System.err.println("trying to connect");
      try {
        bs.connect();
      } catch (IOException e) {
    	try {
          bs.close();
        } catch (IOException e1) {
      	  System.err.println("fail");
        	error = true;
      	  handlerError.sendEmptyMessage(0);
        }
  	    System.err.println("fail");
    	error = true;
  	    handlerError.sendEmptyMessage(0);
      }
      if (!error) {
	      System.err.println("connection is established");
	      handler.sendEmptyMessage(0);
	      ApplicationControler ac = (ApplicationControler)getApplicationContext();
	      ac.set_socket(bs);
	      Intent intent = new Intent(_parent, Game.class);
	      intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
	      intent.putExtra("GAME_MODE", Const.globalServer);
	      startActivity(intent);
      }
    }
    
    private Handler handlerError = new Handler() {
        //@Override
        public void handleMessage(Message msg) {
          pd.dismiss();
          alert.show();
        }
      };
    
    private Handler handler = new Handler() {
      //@Override
      public void handleMessage(Message msg) {
        pd.dismiss();
      }
    };
  }
}
